package com.hangsu.train.core.shiro;

import com.hangsu.train.components.constants.JwtConstant;
import com.hangsu.train.components.dto.SecurityRespDto;
import com.hangsu.train.components.entity.User;
import com.hangsu.train.components.service.SecurityService;
import com.hangsu.train.components.service.UserService;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.SignedJWT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.CollectionUtils;

import java.util.List;

@Slf4j
public class MtRealm extends AuthorizingRealm {

    private UserService userService;

    private SecurityService securityService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void setSecurityService(SecurityService securityService) {
        this.securityService = securityService;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        if (!principalCollection.isEmpty()) {
            User user = (User) principalCollection.getPrimaryPrincipal();
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            SecurityRespDto security = securityService.getUserSecurity(user.getUserCode());
            if(security!=null){
                authorizationInfo.setRoles(security.getRoles());
                authorizationInfo.setStringPermissions(security.getPermissions());
            }
            return authorizationInfo;
        }
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        try {
            String jwtToken = (String) authenticationToken.getCredentials();
            if (StringUtils.isNotEmpty(jwtToken)) {
                SignedJWT signedJWT = SignedJWT.parse(jwtToken);
                String subject = signedJWT.getJWTClaimsSet().getSubject();

                JWSVerifier verifier = new MACVerifier(JwtConstant.SECRET);
                boolean verify = signedJWT.verify(verifier);
                User user = userService.getUserByAccount(subject);
                if (verify && user != null) {
                    List<User> principals = CollectionUtils.asList(user);
                    SimplePrincipalCollection principalCollection = new SimplePrincipalCollection(principals, this.getName());
                    return new SimpleAuthenticationInfo(principalCollection, authenticationToken.getCredentials());
                }
            }
        } catch (Exception exception) {
            log.error(exception.getMessage(), exception);
        }
        throw new AuthenticationException("");
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token != null && BearerToken.class.isAssignableFrom(token.getClass());
    }
}